/*******************************************************************************
 * Copyright (c) 2023 Gradle Inc. and others
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 ******************************************************************************/
package org.eclipse.buildship.dcl.provider;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.eclipse.buildship.core.internal.CorePlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
import org.eclipse.lsp4e.server.StreamConnectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

public class DeclarativeGradleConnectionProvider extends ProcessStreamConnectionProvider implements StreamConnectionProvider {

    private static ILog log;

    public static ILog getLog() {
        if (log == null) {
            Bundle bundle = FrameworkUtil.getBundle(DeclarativeGradleConnectionProvider.class);
            log = Platform.getLog(bundle);
        }
        return log;
    }

    @SuppressWarnings("restriction")
    public DeclarativeGradleConnectionProvider() {
        Bundle bundle = FrameworkUtil.getBundle(DeclarativeGradleConnectionProvider.class);
        try {
            URL localFileURL = FileLocator.toFileURL(bundle.getEntry("/"));
            Path pathToPlugin = Paths.get(localFileURL.toURI());

            // Get the LSP JAR path
            final String lspJarPath = CorePlugin.configurationManager().loadWorkspaceConfiguration().getLspJarPath();
            if (lspJarPath.isBlank()) {
                throw new RuntimeException("LSP JAR path is not set!");
            }

            IExecutionEnvironment[] executionEnvironments = JavaRuntime.getExecutionEnvironmentsManager().getExecutionEnvironments();
            IExecutionEnvironment java11Environment = null;

            for (IExecutionEnvironment environment : executionEnvironments) {
                if (environment.getId().equals("JavaSE-11")) {
                    java11Environment = environment;
                    break;
                }
            }

            ArrayList<IVMInstall> compatibleJVMs = new ArrayList<>(Arrays.asList(java11Environment.getCompatibleVMs()));
            IVMInstall defaultVMInstall = JavaRuntime.getDefaultVMInstall();
            IVMInstall javaExecutable = null;

            if (!compatibleJVMs.isEmpty()) {
                if (compatibleJVMs.contains(defaultVMInstall)) {
                    javaExecutable = defaultVMInstall;
                } else {
                    javaExecutable = compatibleJVMs.get(0);
                }

                String pathToJavaExecutable = javaExecutable.getInstallLocation().toPath().resolve("bin").resolve("java").toString();

                List<String> commands = Arrays.asList(
                        pathToJavaExecutable,
                        //"-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5015,suspend=y",
                        "-jar", lspJarPath);

                // add in commands path to bin application of language server
                setCommands(commands);
                setWorkingDirectory(pathToPlugin.toString());

                // Write to the output that we are starting the server
                System.out.println("Starting server with commands: " + commands);
            } else {
                PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {

                    @Override
                    public void run() {
                        Shell shell = new Shell();
                        MessageBox messageBox = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK);
                        messageBox.setText("Error");
                        messageBox.setMessage("Compatible version of Java isn't found! Install and rerun application.");
                        messageBox.open();
                        shell.dispose();
                    }
                });
            }

        } catch (IOException | URISyntaxException e) {
            System.err.println("[GradlePropertiesConnectionProvider]:" + e.toString());
            e.printStackTrace();
        }
    }

}